package cn.sc.summer.core.util.file;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.Base64;
import java.util.Hashtable;

/**
 * 类名：zxing图形工具类
 *
 * @author a-xin
 * @date 2023/11/28 11:26
 */
@Slf4j
@Component
public class ImageUtil {

    /**
     * 图片路径转Base64字符串
     *
     * @param filePath 文件路径
     * @return base64编码数据
     */
    public static String convertImageToBase64(@NonNull String filePath) {
        ByteArrayOutputStream baos = null;
        try {
            String suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
            File imageFile = new File(filePath);
            BufferedImage bufferedImage = ImageIO.read(imageFile);
            baos = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, suffix, baos);
            byte[] bytes = baos.toByteArray();
            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * Base64字符串转图片
     *
     * @param base64   base64编码
     * @param filePath 文件路径
     */
    public static void convertBase64StrToImage(@NonNull String base64, @NonNull String filePath) {
        ByteArrayInputStream bais = null;
        try {
            String suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
            byte[] bytes = Base64.getDecoder().decode(base64);
            bais = new ByteArrayInputStream(bytes);
            BufferedImage bufferedImage = ImageIO.read(bais);
            File imageFile = new File(filePath);
            ImageIO.write(bufferedImage, suffix, imageFile);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bais != null) {
                    bais.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 文本生成二维码转base64
     *
     * @param content 文本信息
     * @param width   宽度
     * @param height  高度
     * @return base64编码图片
     * @throws Exception io异常
     */
    public static String generateQRToBase64(@NonNull String content, int width, int height) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        MatrixToImageWriter.writeToStream(bitMatrix, "PNG", outputStream);
        Base64.Encoder encoder = Base64.getEncoder();
        return "data:image/jpeg;base64," + encoder.encodeToString(outputStream.toByteArray());
    }

    /**
     * 文本生成二维码到response流
     *
     * @param content  文本信息
     * @param width    宽度
     * @param height   高度
     * @param response 二维码返回载体
     * @throws Exception io异常
     */
    public static void generateQRToStream(@NonNull String content, int width, int height, HttpServletResponse response) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        MatrixToImageWriter.writeToStream(bitMatrix, "PNG", response.getOutputStream());
    }

    /**
     * 文本生成二维码到文件
     *
     * @param content  文本信息
     * @param width    宽度
     * @param height   高度
     * @param filePath 文件地址
     * @throws Exception io异常
     */
    public static void generateQRToFile(@NonNull String content, int width, int height, String filePath) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        Path path = FileSystems.getDefault().getPath(filePath);
        MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);
    }

    /**
     * 生成带logo的二维码
     *
     * @param content  二维码信息
     * @param width    宽度
     * @param height   高度
     * @param logoPath logo地址
     * @param filePath 生成图片地址
     * @throws Exception io异常
     */
    public static void generateQRToFileWithLogo(@NonNull String content, int width, int height, String logoPath, String filePath) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix, new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF));
        Graphics2D graphics = image.createGraphics();
        int logoWidth = image.getWidth() / 5;
        int logoHeight = image.getHeight() / 5;
        int logoX = (image.getWidth() - logoWidth) / 2;
        int logoY = (image.getHeight() - logoHeight) / 2;
        BufferedImage logo = ImageIO.read(new File(logoPath));
        graphics.drawImage(logo, logoX, logoY, logoWidth, logoHeight, null);
        graphics.dispose();
        ImageIO.write(image, "PNG", new File(filePath));
    }

}
